#include"Blockqueue.hpp"
#include"Task.hpp"
#include<time.h>
#include<unistd.h>


template<class C ,class S>
class Blockqueues
{
    public:
        Blockqueue<C> *cq;
        Blockqueue<S> *sq;
};

void* productor(void* bqs_)
{
    Blockqueue<CalTask>* bq = (static_cast<Blockqueues<CalTask,SaveTask>*>(bqs_))->cq;
    while(true)
    {
        int x = rand() % 100 + 1;
        int y = rand() % 10;
        int opercode = rand()%oper.size();
        CalTask t(x,y,oper[opercode],mymath);

        bq->push(t);
        std::cout<<"生产计算任务:"<<t.toTaskstring()<<std::endl;
        sleep(2);
    }
    return nullptr;
}


void* consumer(void* bqs_)
{
    Blockqueue<CalTask>* bq = (static_cast<Blockqueues<CalTask,SaveTask>*>(bqs_))->cq;
    Blockqueue<SaveTask>* savebq = (static_cast<Blockqueues<CalTask,SaveTask>*>(bqs_))->sq;
    while(true)
    {
        CalTask t;
        bq->pop(&t);
        std::string res = t();
        std::cout<<"完成计算任务:"<<res<<"....done"<<std::endl;

        // SaveTask save(res,Save);
        // savebq->push(save);
        // std::cout<<"推送储存任务完成....."<<std::endl;
        //sleep(1);
    }
    return nullptr;
}

void* saver(void* bqs_)
{
    Blockqueue<SaveTask>* savebq = (static_cast<Blockqueues<CalTask,SaveTask>*>(bqs_))->sq;
    while(true)
    {
        SaveTask s;
        savebq->pop(&s);
        s();
        std::cout<<"保存任务完成:"<<"....done"<<std::endl;
    }
    return nullptr;
}

int main()
{
    srand((unsigned long)time(nullptr)^getpid());
    Blockqueues<CalTask,SaveTask> bqs;
    bqs.cq = new Blockqueue<CalTask>();
    bqs.sq = new Blockqueue<SaveTask>();

    pthread_t c[2],p[3];
    pthread_create(p,nullptr,productor,&bqs);
    pthread_create(p+1,nullptr,productor,&bqs);
    pthread_create(p+1,nullptr,productor,&bqs);
    sleep(1);
    pthread_create(c,nullptr,consumer,&bqs);
    pthread_create(c+1,nullptr,consumer,&bqs);

    pthread_join(c[0],nullptr);
    pthread_join(c[1],nullptr);
    pthread_join(p[0],nullptr);
    pthread_join(p[1],nullptr);
    pthread_join(p[2],nullptr);

    delete bqs.cq;
    delete bqs.sq;
    return 0;
}